

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

typedef YKHandlerNameCallBack = Future Function(String message, void Function(String callBackJavaScript) callBack);

class YKWebConfig {

  static YKWebConfig? _instance;
  factory YKWebConfig.getInstance() {
    _instance ??= YKWebConfig._();
    return _instance!;
  }
  YKWebConfig._();

  Map<String,YKHandlerNameCallBack> _handleMap = {};

  String? Function(String? userAgent)? setUserAgentCallBack;

  void Function(Uri uri)? toSystemCallBack;

  Color? progressBgColor;

  Color? progressColor;

  void addUserContent(String handlerName, YKHandlerNameCallBack ykHandlerNameCallBack) {
    _handleMap.addAll({handlerName:ykHandlerNameCallBack});
  }
}

class YKWebWidgetController {

  YKWebWidget? _widget;

  Color? progressBgColor;

  Color? progressColor;

  String? Function(String? userAgent)? setUserAgentCallBack;

  Map<String,YKHandlerNameCallBack> _handleMap = {};

  void addUserContent(String handlerName, YKHandlerNameCallBack ykHandlerNameCallBack) {
    _handleMap.addAll({handlerName:ykHandlerNameCallBack});
  }
  void loadUrl(String url) {
    _widget?._state._loadUrl(url);
  }
  
  YKWebWidgetController({this.progressColor, this.progressBgColor, this.setUserAgentCallBack});
}

class YKWebWidget extends StatefulWidget {

  String title = "";
  final String url;
  YKWebWidgetController? _controller;

  set controller(YKWebWidgetController value) {
    _controller = value;
    _controller?._widget = this;
  }

  YKWebWidget({
    super.key,
    required this.url,
    this.title = "",
    YKWebWidgetController? controller,
  }) {
    _controller = controller;
    _controller?._widget = this;
  }

  _YKWebWidgetState _state = _YKWebWidgetState();

  @override
  State<StatefulWidget> createState() => _state;

}

class _YKWebWidgetState extends State<YKWebWidget> {

  final WebViewController _controller = WebViewController();
  double _webProgress = 0.0;

  Map<String,YKHandlerNameCallBack> _handleMap = {};

  @override
  void initState() {

    _controller.setNavigationDelegate(NavigationDelegate(
        onProgress: (int progress) {
          _webProgress = progress / 100;
          setState(() { });
        },
        onPageStarted: (String url) { },
        onPageFinished: (String url) {},
        onWebResourceError: (WebResourceError error) {},
        onNavigationRequest: (NavigationRequest request) {
          if ((!request.url.startsWith('http') && !request.url.contains("about:"))  ||
              request.url.contains("openapi.alipay.com")) {
            if (YKWebConfig.getInstance().toSystemCallBack != null) {
              YKWebConfig.getInstance().toSystemCallBack!(Uri.parse(request.url));
            }
            return NavigationDecision.prevent;
          }
          return NavigationDecision.navigate;
        }
    ));

    _initWithAsync(() async {
      _controller.loadRequest(Uri.parse(widget.url));

      if (widget._controller != null) {
        for (String key in  widget._controller!._handleMap.keys) {
          YKHandlerNameCallBack callBack = await widget._controller!._handleMap[key]!;
          _controller.addJavaScriptChannel(key, onMessageReceived: (message) {
            callBack(message.message, (callBackJavaScript) {
              _controller.runJavaScript(callBackJavaScript);
            });
          });
        }
      }
    });
    
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    return  Column(
      children: [
        _topInfo(),
        Expanded(child: WebViewWidget(controller: _controller)),
      ],
    );
  }

  Widget _topInfo() {
    if (_webProgress == 0.0 || _webProgress ==1) {
      return const SizedBox();
    } else {
      var bgColor = YKWebConfig.getInstance().progressBgColor;

      Color? valueColor = YKWebConfig.getInstance().progressColor;

      if (widget._controller != null) {
        if (widget._controller!.progressBgColor != null) {
          bgColor = widget._controller!.progressBgColor;
        }
        if (widget._controller!.progressColor != null) {
          valueColor = widget._controller!.progressColor;
        }
      }

      return LinearProgressIndicator(
        value: _webProgress,
        backgroundColor: bgColor,
        valueColor: (valueColor != null) ? AlwaysStoppedAnimation<Color>(valueColor!) : null,
      );
    }
  }

  void _initWithAsync(Future Function() finishCallBack) async {
    await _controller.setJavaScriptMode(JavaScriptMode.unrestricted);
    if (YKWebConfig.getInstance().setUserAgentCallBack != null) {
      final userAgent = await _controller.getUserAgent();
      final afterUserAgent = YKWebConfig.getInstance().setUserAgentCallBack!(userAgent);
      await _controller.setUserAgent(afterUserAgent);
      await finishCallBack();
    }
  }
  
  void _loadUrl(String url) {
    _controller.loadRequest(Uri.parse(widget.url));
  }
}